<?php
/**
 * *
 *  * ============================================================================
 *  * Created by PhpStorm.
 *  * User: Ice
 *  * 邮箱: ice@sbing.vip
 *  * 网址: https://sbing.vip
 *  * Date: 2019/9/20 下午5:19
 *  * ============================================================================.
 */

declare(strict_types=1);

namespace app\common\service;

use Symfony\Component\Translation\Loader\LoaderInterface;
use think\exception\HttpResponseException;
use think\facade\App;
use think\facade\Console;
use think\Response;
use think\Service;
use think\facade\Env;
use think\helper\Str;
use think\facade\Cache;
use think\facade\Event;
use think\facade\Route;
use think\facade\Config;
use app\common\middleware\Addon;
use app\common\middleware\FastInit;

/**
 * 插件服务
 */
class AddonService extends Service
{
    //addons_state
    const ADDONS_STATE = 'addons_state';//插件状态缓存key
    const APP_STATE = 'app_state';//应用状态缓存key
    //addons_list
    const ADDONS_LIST = 'addons_list';//插件列表缓存key
    //prefix
    const ADDONS_INFO = 'addons_info';//插件加载缓存key
    protected $all_addons = [];
    public function register()
    {
        // 插件目录
        ! defined('ADDON_PATH') && define('ADDON_PATH', app()->getRootPath().'addons'.DIRECTORY_SEPARATOR);
        ! defined('DS') && define('DS', DIRECTORY_SEPARATOR);
        // 如果插件目录不存在则创建
        if (! is_dir(ADDON_PATH)) {
            @mkdir(ADDON_PATH, 0755, true);
        }
        $data = request()->get();
       $not_param = [
           'addon',
           'controller',
           'module',
           'action'
       ];
       if(!empty($data)){
           $keys = array_keys($data);
           foreach ($keys as $key){
               if(in_array($key,$not_param)){
                  exit(json_encode([
                      'code'=>0,
                      'msg'=>"参数不允许出现{$key}",
                      'data'=>null
                  ],JSON_UNESCAPED_UNICODE));
               }
           }
       }
        //插件处理
        $this->addon_handle();
    }
    protected function error($msg)
    {
        $result = [
            'code' => 0,
            'msg'  => $msg,
            'data' => null,
        ];
        throw new \Exception(json_encode($result, JSON_UNESCAPED_SLASHES|JSON_PARTIAL_OUTPUT_ON_ERROR), 500);
//        $header = [];
//        $response = Response::create($result, 'json')->header($header);
//
//        throw new HttpResponseException($response);
    }
    public function boot()
    {

    }

    /**
     * 获取缓存.
     * @param string $addon
     * @return array|mixed
     */
    protected function getCache(string $addon)
    {
        $addon_key = self::ADDONS_INFO;
        $has = Cache::get($addon_key);
        $debug = \config('app.app_debug');
        if(empty($has)||$debug||empty($has[$addon])){
            $has[$addon] = [
                'path'=>get_addons_dir($addon),
                'info'=>get_addons_info($addon),
                'config'=>get_addons_config($addon,true),
                'route_path'=>get_addons_route($addon),
                'service'=>get_addons_service($addon),
//                'provide'=>get_addons_provider($addon),
                'middleware'=>get_addons_middleware($addon),
                'event'=>get_addons_event($addon),
                'command'=>get_addons_command($addon),
                'common_path'=>get_addons_common_path($addon),
                'class_name'=>get_addons_class($addon)
            ];
            Cache::set($addon_key,$has);
        }
        return $has[$addon];
    }
    protected function getAllCache()
    {
        $addon_key = self::ADDONS_INFO;
        $has = Cache::get($addon_key);
        $debug = \config('app.app_debug');
        if(empty($has)||!empty($debug)){
            $has = [];
            foreach ($this->all_addons as $addon){
                $has[$addon] = [
                    'path'=>get_addons_dir($addon),
                    'info'=>get_addons_info($addon),
                    'config'=>get_addons_config($addon,true),
                    'route_path'=>get_addons_route($addon),
                    'service'=>get_addons_service($addon),
//                'provide'=>get_addons_provider($addon),
                    'middleware'=>get_addons_middleware($addon),
                    'event'=>get_addons_event($addon),
                    'command'=>get_addons_command($addon),
                    'common_path'=>get_addons_common_path($addon),
                    'class_name'=>get_addons_class($addon)
                ];
            }
            Cache::set($addon_key,$has);
        }
        return $has;
    }

    /**
     * 插件处理.
     * @param string $addon
     * @param array $info
     * @return void
     */
    protected function addons_handle(string $addon,array $info)
    {
        if(!request()->isCli()){
            $url = request()->url();
            $url = trim($url,'/');
            $module = 'index';
            if(!empty($url)){
                $url_array = explode('/',$url);
                $module = $url_array[0]??null;
            }

            $url = str_replace('addons/','',$url);
            $url_list = explode('/',$url);
            $constroller = $url_list[1]??null;
            $action = $url_list[2]??null;
            $addon_module = null;
            if(!empty($constroller)){
                $constroller_array = explode('.',$constroller);
                $addon_module = strtolower($constroller_array[0])??null;
            }

        }
        //加载插件全局函数库
        if(!empty($info['common_path'])){
            if(request()->isCli()){
                //命令行下载入所有公共函数库
                foreach ($info['common_path'] as $common_path){
                    if(is_array($common_path)){
                        foreach ($common_path as $common_path_file){
                            include $common_path_file;
                        }
                    }

                }
            }else{
                //加载插件全局函数库
                if(!empty($info['common_path']['base'])){
                    include $info['common_path']['base'];
                }
                //加载插件模块函数库
                if(!empty($addon_module)){
                    if(!empty($info['common_path'][$addon_module])){
                        include $info['common_path'][$addon_module];
                    }
                }
            }
        }
        //加载插件命令行工具
        if(!empty($info['command'])){
            //只有命令行模式下加载
            if(request()->isCli()){
                $this->commands($info['command']);
            }
        }
        //加载插件事件
        if(!empty($info['event'])){
            if(!empty($info['event']['bind'])){
                foreach ($info['event']['bind'] as $key=>$bind){
                    $this->app->bind($key,$bind);
                }
            }
            if(!empty($info['event']['listen'])){
                $this->app->event->listenEvents($info['event']['listen']);
            }
            if(!empty($info['event']['subscribe'])){
                $this->app->event->subscribe($info['event']['subscribe']);
            }
        }
        //调用插件appinit
        if(!empty($info['class_name'])&&method_exists($info['class_name'],'app_init')){
            $obj = new $info['class_name'];
            $obj->app_init();
        }


        //加载插件服务
        if(!empty($info['service'])){
            //命令行模式下加载
            if(request()->isCli()){
                foreach ($info['service'] as $service){
                    if(is_array($service)){
                        foreach ($service as $service_item){
                            $this->app->register($service_item);
                        }
                    }
                }
            }else{
                //模块模式下加载
                if(!empty($info['service']['base'])){
                    foreach ($info['service']['base'] as $service){
                        $this->app->register($service);
                    }
                }
                if(!empty($addon_module)){
                    if(!empty($info['service'][$addon_module])){
                        foreach ($info['service'][$addon_module] as $service){
                            $this->app->register($service);
                        }
                    }
                }

            }
        }
        $middleware = [
//            FastInit::class,
//            Addon::class,
        ];
        //加载插件跟中间件
        if(!empty($info['middleware']['base'])){
            $middleware = array_merge($middleware,$info['middleware']['base']);
        }
        if(!request()->isCli()){
            //加载插件模块中间件,非命令行模式
            if(!empty($info['middleware'][$module])){
                $middleware = array_merge($middleware,$info['middleware'][$module]);
            }
        }
        if($module=='addons'){
            if(isset($info['info']['autorouter'])&&$info['info']['autorouter']==1){
                //插件自动路由
                Route::rule('addons/:addon/[:module]/[:controller]/[:action]', '\\think\\addons\\Route::execute')->middleware($middleware);
            }else{
                //插件配置路由
                if(!empty($info['route_path'])){
                    //循环加载路由文件
                    foreach ($info['route_path'] as $route_path){
                        include $route_path;
                    }
                }
            }
        }

    }
    /**
     * 注册插件路由.
     */
    private function addon_handle()
    {
        $app_debug = \config('app.app_debug');
        $addonsList = get_state_addons($app_debug);
//        echo '<pre>';
//        print_r($addonsList);
//        exit;
        if(empty($addonsList)){
            return true;
        }
        $this->all_addons = $addonsList;
        $allCache = $this->getAllCache();
        foreach ($addonsList as $addon){
            $this->addons_handle($addon,$allCache[$addon]??[]);
        }
    }
}
